From 154cc0aa54500789613fbeb0434fadcdee29f5a5 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 29 Nov 2016 13:19:07 -0500 Subject: [PATCH] Warn when crates.io sends back invalid category slugs --- src/cargo/ops/registry.rs | 21 +++++++++++++++++---- src/crates-io/lib.rs | 28 +++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index af80760b6..2b4447609 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -133,7 +133,7 @@ fn transmit(config: &Config, return Ok(()); } - registry.publish(&NewCrate { + let publish = registry.publish(&NewCrate { name: pkg.name().to_string(), vers: pkg.version().to_string(), deps: deps, @@ -148,9 +148,22 @@ fn transmit(config: &Config, repository: repository.clone(), license: license.clone(), license_file: license_file.clone(), - }, tarball).map_err(|e| { - human(e.to_string()) - }) + }, tarball); + + match publish { + Ok(invalid_categories) => { + if !invalid_categories.is_empty() { + let msg = format!("\ + the following are not valid category slugs and were \ + ignored: {}. Please see https://crates.io/category_slugs \ + for the list of all category slugs. \ + ", invalid_categories.join(", ")); + config.shell().warn(&msg)?; + } + Ok(()) + }, + Err(e) => Err(human(e.to_string())), + } } pub fn registry_configuration(config: &Config) -> CargoResult { diff --git a/src/crates-io/lib.rs b/src/crates-io/lib.rs index 4d8d889f3..12c195edb 100644 --- a/src/crates-io/lib.rs +++ b/src/crates-io/lib.rs @@ -10,7 +10,7 @@ use std::io::{self, Cursor}; use std::result; use curl::easy::{Easy, List}; -use rustc_serialize::json; +use rustc_serialize::json::{self, Json}; use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET}; @@ -39,6 +39,7 @@ pub enum Error { NotFound, JsonEncodeError(json::EncoderError), JsonDecodeError(json::DecoderError), + JsonParseError(json::ParserError), } impl From for Error { @@ -53,6 +54,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: json::ParserError) -> Error { + Error::JsonParseError(err) + } +} + impl From for Error { fn from(err: curl::Error) -> Error { Error::Curl(err) @@ -111,7 +118,6 @@ pub struct User { #[derive(RustcDecodable)] struct Users { users: Vec } #[derive(RustcDecodable)] struct TotalCrates { total: u32 } #[derive(RustcDecodable)] struct Crates { crates: Vec, meta: TotalCrates } - impl Registry { pub fn new(host: String, token: Option) -> Registry { Registry::new_handle(host, token, Easy::new()) @@ -148,7 +154,8 @@ impl Registry { Ok(json::decode::(&body)?.users) } - pub fn publish(&mut self, krate: &NewCrate, tarball: &File) -> Result<()> { + pub fn publish(&mut self, krate: &NewCrate, tarball: &File) + -> Result> { let json = json::encode(krate)?; // Prepare the body. The format of the upload request is: // @@ -191,10 +198,20 @@ impl Registry { headers.append(&format!("Authorization: {}", token))?; self.handle.http_headers(headers)?; - let _body = handle(&mut self.handle, &mut |buf| { + let body = handle(&mut self.handle, &mut |buf| { body.read(buf).unwrap_or(0) })?; - Ok(()) + // Can't derive RustcDecodable because JSON has a key named "crate" :( + let response = Json::from_str(&body)?; + let invalid_categories: Vec = + response + .find_path(&["warnings", "invalid_categories"]) + .and_then(Json::as_array) + .map(|x| { + x.iter().flat_map(Json::as_string).map(Into::into).collect() + }) + .unwrap_or_else(Vec::new); + Ok(invalid_categories) } pub fn search(&mut self, query: &str, limit: u8) -> Result<(Vec, u32)> { @@ -329,6 +346,7 @@ impl fmt::Display for Error { Error::NotFound => write!(f, "cannot find crate"), Error::JsonEncodeError(ref e) => write!(f, "json encode error: {}", e), Error::JsonDecodeError(ref e) => write!(f, "json decode error: {}", e), + Error::JsonParseError(ref e) => write!(f, "json parse error: {}", e), } } } -- 2.30.2